package org.elanfox.intellicommunity.biz.service.core.alarm.impl;

import org.elanfox.intellicommunity.biz.dto.msg.LocationMsgDTO;
import org.elanfox.intellicommunity.biz.entity.equipment.LocatorAreaPO;
import org.elanfox.intellicommunity.biz.entity.equipment.LocatorPO;
import org.elanfox.intellicommunity.biz.entity.resident.LocatorStructureRelPO;
import org.elanfox.intellicommunity.biz.entity.resident.WorkerPO;
import org.elanfox.intellicommunity.biz.repository.msg.AlarmMsgRepository;
import org.elanfox.intellicommunity.biz.service.core.alarm.AlarmManageService;
import org.elanfox.intellicommunity.biz.service.core.equipment.LocatorAreaService;
import org.elanfox.intellicommunity.biz.service.core.equipment.LocatorService;
import org.elanfox.intellicommunity.biz.service.core.msg.LocationMsgService;
import org.elanfox.intellicommunity.biz.service.core.resident.LocatorStructureService;
import org.elanfox.intellicommunity.biz.service.core.resident.WorkerService;
import org.elanfox.intellicommunity.common.ienum.CommonEnums;
import org.elanfox.intellicommunity.common.ienum.EquipmentEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author allan
 * @version 1.0.0
 * @date 1/21/21
 */
@Service
public class AlarmManageServiceImpl implements AlarmManageService {
    @Autowired
    private AlarmMsgRepository alarmMsgRepository;
    @Autowired
    private LocatorService locatorService;
    @Autowired
    private LocationMsgService locationMsgService;
    @Autowired
    private WorkerService workerService;
    @Autowired
    private LocatorStructureService locatorStructureService;
    @Autowired
    private LocatorAreaService locatorAreaService;

    /**
     * 得到在所给出的定位器集合中的管家列表
     *
     * @param stewards
     * @param locatorPOS
     * @return
     */
    private List<WorkerPO> stewardsIn(List<WorkerPO> stewards, List<LocatorPO> locatorPOS) {
        List<WorkerPO> list = new ArrayList<>();
        for (WorkerPO steward : stewards) {
            //查看当前管家所处的位置
            LocationMsgDTO dto = locationMsgService.findLastByUser(steward.getUser().getUserId());

            if (dto != null) {
                if (locatorPOS.stream().anyMatch(p -> p.getNo().equals(dto.getLocatorId()))) {
                    list.add(steward);
                }
            }
        }
        return list;
    }

    @Override
    public Map<Integer, List<WorkerPO>> findNearby(Long locatorId) {
        LocatorPO locatorPO = locatorService.findByNo(locatorId);

        if (locatorPO.getType() == EquipmentEnum.TypeEnum.TYPE_2) {
            //室外的逻辑
            return this.findNearByByArea(locatorPO.getAreaPO().getId());
        } else {
            //室内的逻辑
            return this.findNearBySameBuilding(locatorId);
        }
    }

    @Override
    public Map<Integer, List<WorkerPO>> findNearBy(Integer userId) {
        LocationMsgDTO dto = locationMsgService.findLastByUser(userId);

        return findNearby(dto.getLocatorId());
    }

    @Override
    public Map<Integer, List<WorkerPO>> findNearByByArea(Integer areaId) {
        Map<Integer, List<WorkerPO>> results = new HashMap<>();

        //得到所有管家
        List<WorkerPO> workerPOS = workerService.findAllSteward();

        //当前区域
        List<LocatorPO> currents = locatorService.findByArea(areaId);
        List<WorkerPO> currentStewards = stewardsIn(workerPOS, currents);
        results.put(CommonEnums.AreaDesc.CURRENT.getCode(), currentStewards);

        LocatorAreaPO areaPO = locatorAreaService.findById(areaId);

        //近区域
        if (areaPO.getClosest() != null) {
            currents = locatorService.findByArea(areaPO.getClosest().getId());
            currentStewards = stewardsIn(workerPOS, currents);
            results.put(CommonEnums.AreaDesc.CLOSEST.getCode(), currentStewards);
        }
        if (areaPO.getMiddle() != null) {
            currents = locatorService.findByArea(areaPO.getClosest().getId());
            currentStewards = stewardsIn(workerPOS, currents);
            results.put(CommonEnums.AreaDesc.MIDDLE.getCode(), currentStewards);
        }
        if (areaPO.getFaraway() != null) {
            currents = locatorService.findByArea(areaPO.getClosest().getId());
            currentStewards = stewardsIn(workerPOS, currents);
            results.put(CommonEnums.AreaDesc.FARAWAY.getCode(), currentStewards);
        }

        return results;
    }

    @Override
    public Map<Integer, List<WorkerPO>> findNearBySameBuilding(Long locatorId) {
        Map<Integer, List<WorkerPO>> results = new HashMap<>();

        LocatorPO locatorPO = locatorService.findByNo(locatorId);

        //先加入负责该楼的管家
        results.put(CommonEnums.AreaDesc.RESPONSIBLE.getCode(), workerService.findWorkerByStructureId(locatorPO.getLocatorInfo().getStructureId()));

        //得到所有管家
        List<WorkerPO> workerPOS = workerService.findAllSteward();

        //得到该楼层所有定位器信息
        List<LocatorPO> locatorPOS = locatorService.findByStructureId(locatorPO.getLocatorInfo().getStructureId());
        List<WorkerPO> currentStewards;
        currentStewards = stewardsIn(workerPOS, locatorPOS);

        //找同楼层的
        if (currentStewards.size() == 0) {
            //找到除了这层以外所有的定位器
            List<LocatorPO> buildingLocators = locatorService.findPStructureLocator(locatorPO.getLocatorInfo().getStructureId());

            currentStewards = stewardsIn(workerPOS, buildingLocators);

            if (currentStewards.size() == 0) {
                //找附近关联的定位器
                List<LocatorStructureRelPO> relatedLocators = locatorStructureService.findNearbyLocator(locatorPO.getLocatorInfo().getStructureId());

                List<LocatorPO> pos = relatedLocators.stream().map(LocatorStructureRelPO::getLocatorPO).collect(Collectors.toList());
                currentStewards = stewardsIn(workerPOS, pos);
            }
        }

        results.put(CommonEnums.AreaDesc.NEARBY.getCode(), currentStewards);

        return results;
    }
}
